package com.changgou.seckill.thread;

import com.changgou.seckill.dao.SeckillGoodsMapper;
import com.changgou.seckill.pojo.SeckillGoods;
import com.changgou.seckill.pojo.SeckillOrder;
import com.changgou.seckill.pojo.SeckillStatus;
import com.changgou.seckill.redislock.RedisSonLock;
import com.netflix.discovery.converters.Auto;
import entity.IdWorker;
import entity.SystemConstants;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Component;

import java.util.Date;
import java.util.concurrent.TimeUnit;

@Component
public class MultiThreadingCreateOrder {

    @Autowired
    private RedisTemplate redisTemplate;

    @Autowired
    private SeckillGoodsMapper seckillGoodsMapper;

    @Autowired
    private IdWorker idWorker;

    @Autowired
    private  RedisSonLock redisSonLock;


    @Async  //多线程下单
    public void createOrder(){

        System.out.println("=============开始下单:=================="+new Date());




        try {
            Thread.sleep(10000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        System.out.println("=============下单结束=================="+new Date());

        //用来设置一个锁名称
        String lockKey = "lockKey";
        try {

            //用来设置获得一个锁 setnx
            //Boolean xiaocao = redisTemplate.opsForValue().setIfAbsent(lockKey, "xiaocao");
            //加锁,设置过期时间
            // 问题: 当前还没有完成锁的时间设置就出现问题,还是会造成死锁
            //redisTemplate.expire(lockKey,10 , TimeUnit.MINUTES);

            //可以有一个原子操作的功能,就是自己设置在获得锁的时候就设置时间
           // redisTemplate.opsForValue().setIfAbsent(lockKey, "xiaocao", 10, TimeUnit.MINUTES);

            redisSonLock.lock();  //分布式锁

            //redis中取出排队的信息
            SeckillStatus  seckillStatus = (SeckillStatus) redisTemplate.boundListOps(SystemConstants.SEC_KILL_USER_QUEUE_KEY).rightPop();

            //时间区间
            String time = seckillStatus.getTime();
            //用户登录名
            String username= seckillStatus.getUsername();
            //用户抢购商品
            Long id = seckillStatus.getGoodsId();


            //1.根据商品的id获取商品的数据
            //redisTemplate.boundHashOps("SeckillGoods_" + time)
            SeckillGoods seckillGoods = (SeckillGoods) redisTemplate.boundHashOps(SystemConstants.SEC_KILL_GOODS_PREFIX + time).get(id);

            //2.判断商品是否存在或者商品的库存是否为0,如果为0,放回:卖完了
            //在队列中取出商品,看看有没有,防止超卖
//            Object o = redisTemplate.boundListOps(SystemConstants.SEC_KILL_CHAOMAI_LIST_KEY_PREFIX + id).rightPop();
//
//            if (o == null){
//                throw  new RuntimeException("商品卖完了");
//            }

            if (seckillGoods == null || seckillGoods.getStockCount()<=0){
                throw  new RuntimeException("商品卖完了");
        }
            //3.库存减少
            seckillGoods.setStockCount(seckillGoods.getStockCount()-1); //库存减1
            //从新设置redis中的数据,库存数等
            redisTemplate.boundHashOps(SystemConstants.SEC_KILL_GOODS_PREFIX + time).put(id,seckillGoods);

            //4.判断商品是否存在或者商品的库存是否为0,如果为0更新到数据库中,删除掉redis中的数据
            if (seckillGoods.getStockCount()<=0){
                seckillGoodsMapper.updateByPrimaryKeySelective(seckillGoods); //更新数据库中的数据
                redisTemplate.boundHashOps(SystemConstants.SEC_KILL_GOODS_PREFIX + time).delete(id);

            }
            //创建预订单
            SeckillOrder seckillOrder = new SeckillOrder();

            seckillOrder.setId(idWorker.nextId()); //设置id
            seckillOrder.setSeckillId(id);   //设置商品的id
            seckillOrder.setMoney(seckillGoods.getPrice()); //设置价格
            seckillOrder.setUserId(username);  //用户名
            seckillOrder.setPayTime(new Date()); //创建时间
            seckillOrder.setStatus("0");

            //把预订单放到redis中
            redisTemplate.boundHashOps(SystemConstants.SEC_KILL_ORDER_KEY).put(username, seckillOrder);

            //抢单成功,更新抢单的状态,排队->等待支付
            seckillStatus.setStatus(2);  //等待支付状态
            seckillStatus.setOrderId(seckillOrder.getId()); //商品id
            seckillStatus.setMoney(Float.valueOf(seckillOrder.getMoney()));

            //重新设置抢单的状态到redis中
            redisTemplate.boundHashOps(SystemConstants.SEC_KILL_USER_STATUS_KEY).put(username, seckillStatus);


        } catch (RuntimeException e) {
            e.printStackTrace();
        }finally {
            redisSonLock.releas();  //分布式解锁
        }


    }
}
